package com.doodle.common.utils;

import android.view.MenuItem;
import android.view.View;
import android.widget.AbsListView;
import android.widget.ListView;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class OnItemDragListenerProxy implements InvocationHandler {
	
	public static final int ACTION_TYPE_NORMAL = 0;
    public static final int ACTION_TYPE_WARNING = 1;
    
	private static Class<?> sListenerClass;
	private static Method sSetListenerMethod;
	private static Method sEnableDragMethod;
	private static Class<?> sSelectionClass;
	private static Class<?> sFilterClass;
	private static Method sSetSelectionMethod;
	private static int sChoiceMode = 4;

	public static Method sGetDragPositionMethod;
	
	private Object mListener;
	private Object mSelection;
	
	static {
		try {
			sListenerClass = Class.forName("android.widget.AbsListView$OnItemDragListener");
			sSelectionClass = Class.forName("android.widget.ListView$OnDragSelectListener");
			sFilterClass = Class.forName("android.widget.AbsListView$DragItemFilter");
			sSetListenerMethod = AbsListView.class.getMethod("setItemDragListener", sListenerClass);
			sEnableDragMethod = ListView.class.getMethod("setEnableDragSelection", boolean.class);
			sSetSelectionMethod = ListView.class.getMethod("setEnableDragSelection", sSelectionClass);
			Field field = AbsListView.class.getField("CHOICE_MODE_MULTIPLE_MODAL_MZ");
			sChoiceMode = field.getInt(null);
		} catch (Exception e) {
			e.printStackTrace();
			sListenerClass = null;
			sSelectionClass = null;
			sFilterClass = null;
			sSetListenerMethod = null;
			sEnableDragMethod = null;
			sSetSelectionMethod = null;
			sChoiceMode = 4;
		}
		try {
			sGetDragPositionMethod = AbsListView.class.getMethod("getDragPosition");
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
			sGetDragPositionMethod = null;
		}
	}

	private Object createListener() {
		return Proxy.newProxyInstance(sListenerClass.getClassLoader(),
				new Class[] { sListenerClass, sFilterClass }, this);
	}
	
	private Object createSelection() {
		return Proxy.newProxyInstance(sSelectionClass.getClassLoader(),
				new Class[] { sSelectionClass }, this);
	}

	@Override
	public Object invoke(Object obj, Method method, Object[] args) {
		Object o = null;
		try {
			String methodName = method.getName();
			if ("onActionItemDragStart".equals(methodName)) {
				o = onActionItemDragStart();
			} else if ("onActionItemDrop".equals(methodName)) {
				onActionItemDrop((MenuItem)args[0], (Integer)args[1], (Long)args[2]);
			} else if ("onActionItemDragEnd".equals(methodName)) {
				onActionItemDragEnd();
			} else if ("getActionItemType".equals(methodName)) {
				o = Integer.valueOf(getActionItemType((MenuItem)args[0]));
			} else if ("onDragSelection".equals(methodName)) {
				o = Boolean.valueOf(onDragSelection((View)args[0], (Integer)args[1], (Long)args[2]));
			} else if ("isItemDragable".equals(methodName)) {
				o = Boolean.valueOf(isItemDragable((View)args[0], (Integer)args[1], (Long)args[2]));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return o;
	}
	
	public static int getDragPosition(AbsListView list) {
		try {
			return (Integer)sGetDragPositionMethod.invoke(list);
		} catch (Exception e) {
			e.printStackTrace();
			return -1;
		}
	}
	
	public void setToList(AbsListView list, boolean needSelection) {
		if (sSetListenerMethod == null || sEnableDragMethod == null) {
			return;
		}
		if (mListener == null) {
			mListener = createListener();
		}
		if (needSelection && mSelection == null) {
			mSelection = createSelection();
		}
		try {
			if (list instanceof ListView) {
				if (needSelection && mSelection != null) {
					sSetSelectionMethod.invoke(list, mSelection);
				} else {
					sEnableDragMethod.invoke(list, true);
				}
			}
			sSetListenerMethod.invoke(list, mListener);
			list.setChoiceMode(sChoiceMode);
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
	}
	
    public int onActionItemDragStart() { return 0; }
    public void onActionItemDrop(MenuItem menuItem, int position, long id) { }
    public void onActionItemDragEnd() { }
    public int getActionItemType(MenuItem menuItem) { return 0; }

    public boolean onDragSelection(View view, int position, long id) { return true; }
    public boolean isItemDragable(View view, int position, long id) { return true; }
    
}